home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / hist.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  10KB  |  450 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "defs.h"
  17. #include "net.h"
  18. #include "ASSERT.h"
  19. #include "globals.h"
  20.  
  21. #ifdef FAULT_SIM
  22. extern    int    fault_mode;
  23. #define    DoingFault    (fault_mode != 0)
  24. #else
  25. #define    DoingFault    (0)
  26. #define    hchange    head        /* for the compiler's sake */
  27. #endif
  28.  
  29.  
  30. public    hptr   freeHist = NULL;        /* list of free history entries */
  31. public  hptr   last_hist;        /* pointer to dummy hist-entry that
  32.                      * serves as tail for all nodes */
  33. public    int    num_edges = 0;
  34. public    int    num_punted = 0;
  35. public    int    num_cons_punted = 0;
  36.  
  37. public    hptr   first_model;        /* first model entry */
  38. private    hptr   curr_model;        /* ptr. to current model entry */
  39.  
  40. private    char   mem_msg[] = "*** OUT OF MEMORY:Will stop collecting history\n";
  41.  
  42.  
  43. public    Ulong  max_time;
  44.  
  45. public void init_hist()
  46.   {
  47.     static HistEnt  dummy;
  48.     static HistEnt  dummy_model;
  49.  
  50.     max_time = MAX_TIME;
  51.  
  52.     last_hist = &dummy;
  53.     dummy.next = last_hist;
  54.     dummy.time = max_time;
  55.     dummy.val = X;
  56.     dummy.inp = 1;
  57.     dummy.punt = 0;
  58.     dummy.t.r.delay = dummy.t.r.rtime = 0;
  59.  
  60.     dummy_model.time = 0;
  61.     dummy_model.val = model_num;
  62.     dummy_model.inp = 0;
  63.     dummy_model.punt = 0;
  64.     dummy_model.next = NULL;
  65.     first_model = curr_model = &dummy_model;
  66.   }
  67.  
  68.  
  69. #define    NEW_HIST( NEW, ACTnoMEM )                    \
  70.   {                                    \
  71.     if( ((NEW) = freeHist) == NULL )                    \
  72.       {                                    \
  73.     if( ((NEW) = (hptr) MallocList( sizeof( HistEnt ), 0 )) == NULL ) \
  74.       {                                \
  75.         lprintf( stderr, mem_msg );                    \
  76.         sm_stat |= OUT_OF_MEM;                    \
  77.         ACTnoMEM;                            \
  78.       }                                \
  79.       }                                    \
  80.     freeHist = (NEW)->next;                        \
  81.   }                                    \
  82.  
  83.  
  84. public void SetFirstHist( node, value, inp, time )
  85.   nptr  node;
  86.   int   value, inp;
  87.   long  time;
  88.   {
  89.     node->head.time = time;
  90.     node->head.val = value;
  91.     node->head.inp = inp;
  92.     node->head.t.r.rtime = node->head.t.r.delay = 0;
  93.   }
  94.  
  95.  
  96. /*
  97.  * Add a new entry to the history list.  Update curr to point to this change.
  98.  */
  99. public void AddHist( node, value, inp, time, delay, rtime )
  100.   register nptr  node;
  101.   int            value;
  102.   int            inp;
  103.   long           time;
  104.   long           delay, rtime;
  105.   {
  106.     register hptr  newh, curr;
  107.  
  108.     num_edges++;
  109.  
  110.     curr = node->curr;
  111.  
  112.     if( sm_stat & OUT_OF_MEM )
  113.         return;
  114.  
  115.     while( curr->next->punt )        /* skip past any punted events */
  116.     curr = curr->next;
  117.  
  118.     NEW_HIST( newh, return );
  119.  
  120.     newh->next = curr->next;
  121.     newh->time = time;
  122.     newh->val = value;
  123.     newh->inp = inp;
  124.     newh->punt = 0;
  125.     newh->t.r.delay = delay;
  126.     newh->t.r.rtime = rtime;
  127.     node->curr = curr->next = newh;
  128.   }
  129.  
  130.  
  131. #define    PuntTime( H )        ( (H)->time - (H)->t.p.ptime )
  132.  
  133.  
  134. /*
  135.  * Add a punted event to the history list for the node.  Consecutive punted
  136.  * events are kept in punted-order, so that h->ptime < h->next->ptime.
  137.  * Adding a punted event does not change the current pointer, which always
  138.  * points to the last "effective" node change.
  139.  */
  140. public void AddPunted( node, ev, tim )
  141.   register nptr  node;
  142.   evptr          ev;
  143.   long           tim;
  144.   {
  145.     register hptr  newp, h;
  146.  
  147.     h = node->curr;
  148.  
  149.     num_punted++;
  150.     if( (sm_stat & OUT_OF_MEM) or DoingFault )
  151.         return;
  152.  
  153.     NEW_HIST( newp, return );        /* allocate the punted event itself */
  154.  
  155.     newp->time = ev->ntime;
  156.     newp->val = ev->eval;
  157.     newp->inp = 0;
  158.     newp->punt = 1;
  159.     newp->t.p.delay = ev->delay;
  160.     newp->t.p.rtime = ev->rtime;
  161.     newp->t.p.ptime = newp->time - tim;
  162.  
  163.     if( h->next->punt )        /* there are some punted events already */
  164.       {
  165.     num_cons_punted++;
  166.     do { h = h->next; } while( h->next->punt );
  167.       }
  168.  
  169.     newp->next = h->next;
  170.     h->next = newp;
  171.   }
  172.  
  173.  
  174. /*
  175.  * Free up a node's history list
  176.  */
  177. public void FreeHistList( node )
  178.   register nptr  node;
  179.   {
  180.     register hptr  h, next;
  181.  
  182.     if( (h = node->head.next) == last_hist )        /* nothing to do */
  183.         return;
  184.  
  185.     while( (next = h->next) != last_hist )        /* find last entry */
  186.     h = next;
  187.  
  188.     h->next = freeHist;                /* link list to free list */
  189.     freeHist = node->head.next;
  190.  
  191.     node->head.next = last_hist;
  192.     node->curr = &(node->head);
  193.  
  194.     sm_stat &= ~OUT_OF_MEM;
  195.   }
  196.  
  197.  
  198.  
  199. public void NoMoreIncSim()
  200.   {
  201.     lprintf( stderr, "*** can't continue incremetal simulation\n" );
  202.     exit( 1 );        /* do something here ? */
  203.   }
  204.  
  205.  
  206. /*
  207.  * Add a new model entry, recording the time of the change.
  208.  */
  209. public void NewModel( nmodel )
  210.   int  nmodel;
  211.   {
  212.     if( curr_model->time != cur_delta )
  213.       {
  214.     hptr newh;
  215.  
  216.     NEW_HIST( newh, NoMoreIncSim() );
  217.  
  218.     newh->next = NULL;
  219.     newh->time = cur_delta;
  220.     newh->val = nmodel;
  221.     curr_model->next = newh;
  222.     curr_model = newh;
  223.       }
  224.     else
  225.     curr_model->val = nmodel;
  226.   }
  227.  
  228.  
  229.  
  230. #define    QTIME( H )        ( (H)->time - (H)->t.r.delay )
  231.  
  232. /*
  233.  * Add a new change to the history list of node 'nd' caused by event 'ev'.
  234.  * Skip past any punted events already in the history and update nd->curr to
  235.  * point to the new change.
  236.  */
  237. public void NewEdge( nd, ev )
  238.   nptr   nd;
  239.   evptr  ev;
  240.   {
  241.     register hptr  p, h, newh;
  242.  
  243.     for( p = nd->curr, h = p->next; h->punt; p = h, h = h->next );
  244.  
  245.     if( DoingFault )
  246.     p = newh = &nd->hchange;
  247.     else
  248.     NEW_HIST( newh, NoMoreIncSim() );
  249.  
  250.     newh->time = ev->ntime;
  251.     newh->val = ev->eval;
  252.     newh->inp = 0;        /* always true in incremental simulation */
  253.     newh->punt = 0;
  254.     newh->t.r.delay = ev->delay;
  255.     newh->t.r.rtime = ev->rtime;
  256.  
  257.     p->next = newh;
  258.     newh->next = h;
  259.  
  260.     nd->curr = newh;        /* newh becomes the current value */
  261.   }
  262.  
  263.  
  264. /*
  265.  * Delete the next effective change (following nd->curr) from the history.
  266.  * Punted events before the next change (in nd->t.punts) can now be freed.
  267.  * Punted events following the deleted edge are moved to nd->t.punts.
  268.  */
  269. public void DeleteNextEdge( nd )
  270.   nptr  nd;
  271.   {
  272.     register hptr  a, b, c;
  273.  
  274.     if( DoingFault )
  275.       {
  276.     if( nd->t.punts != NULL ) lprintf( stderr, "non-null punts\n" );
  277.     
  278.     if( nd->curr != &nd->hchange )
  279.       {
  280.         nd->hchange = *nd->curr;
  281.         nd->curr = &nd->hchange;
  282.       }
  283.     
  284.     a = nd->curr;
  285.     for( b = a->next; b->punt; a = b, b = b->next );
  286.  
  287.     nd->hchange.next = b->next;    /* b->next => punt before next edge */
  288.     nd->t.punts = NULL;
  289.     return;
  290.       }
  291.  
  292.     if( (a = nd->t.punts) != NULL )    /* remove previously punted events */
  293.       {
  294.     for( b = a; b->next != NULL; b = b->next );
  295.     b->next = freeHist;
  296.     freeHist = a;
  297.       }
  298.  
  299.     a = nd->curr;
  300.     for( b = a->next; b->punt; a = b, b = b->next );
  301.     for( c = b->next; c->punt; b = c, c = c->next );
  302.     c = a->next;            /* c => next edge */
  303.     a->next = b->next;
  304.     a = c->next;            /* a => first punted event after c */
  305.  
  306.     c->next = freeHist;            /* free the next effective change */
  307.     freeHist = c;
  308.  
  309.     if( a->punt )            /* move punted events from hist */
  310.       {
  311.     nd->t.punts = a;
  312.     b->next = NULL;
  313.       }
  314.     else
  315.     nd->t.punts = NULL;
  316.   }
  317.  
  318.  
  319. #define    NEXTH( H, P )    for( (H) = (P)->next; (H)->punt; (H) = (H)->next )
  320.  
  321. public void FlushHist( ftime )
  322.   register Ulong  ftime;
  323.   {
  324.     register nptr  n;
  325.     register hptr  h, p, head;
  326.  
  327.     for( n = GetNodeList(); n != NULL; n = n->n.next )
  328.       {
  329.     head = &(n->head);
  330.     if( head->next == last_hist or (n->nflags & ALIAS) )
  331.         continue;
  332.     p = head;
  333.     NEXTH( h, p );
  334.     while( h->time < ftime )
  335.       {
  336.         p = h;
  337.         NEXTH( h, h );
  338.       }
  339.     head->val = p->val;
  340.     head->time = p->time;
  341.     head->inp = p->inp;
  342.     while( p->next != h )
  343.         p = p->next;
  344.     if( head->next != h )
  345.       {
  346.         p->next = freeHist;
  347.         freeHist = head->next;
  348.         head->next = h;
  349.       }
  350.     if( n->curr->time < ftime )
  351.       {
  352.         n->curr = head;
  353.       }
  354.       }
  355.   }
  356.  
  357.  
  358. public int backToTime( nd )
  359.   register nptr  nd;
  360.   {
  361.     register hptr  h, p;
  362.  
  363.     if( nd->nflags & (ALIAS | MERGED) )
  364.     return( 0 );
  365.  
  366.     h = &(nd->head);
  367.     NEXTH( p, h );
  368.     while( p->time < cur_delta )
  369.       {
  370.     h = p;
  371.     NEXTH( p, p );
  372.       }
  373.     nd->curr = h;
  374.  
  375.     /* queue pending events */
  376.     for( p = h, h = p->next; ; p = h, h = h->next )
  377.       {
  378.     long  qtime;
  379.  
  380.     if( h->punt )
  381.       {
  382.         if( PuntTime( h ) < cur_delta )    /* already punted, skip it */
  383.         continue;
  384.  
  385.         qtime = h->time - h->t.p.delay;    /* pending, enqueue it */
  386.         if( qtime < cur_delta )
  387.           {
  388.         Ulong tmp = cur_delta;
  389.         cur_delta = qtime;
  390.         enqueue_event( nd, (int) h->val, (long) h->t.p.delay,
  391.           (long) h->t.p.rtime );
  392.         cur_delta = tmp;
  393.           }
  394.         p->next = h->next;
  395.         h->next = freeHist;
  396.         freeHist = h;
  397.         h = p;
  398.       }
  399.     else
  400.       {
  401.         qtime = QTIME( h );
  402.         if( qtime < cur_delta )        /* pending, enqueue it */
  403.           {
  404.         Ulong tmp = cur_delta;
  405.         cur_delta = qtime;
  406.         enqueue_event( nd, (int) h->val, (long) h->t.r.delay,
  407.           (long) h->t.r.rtime );
  408.         cur_delta = tmp;
  409.  
  410.         p->next = h->next;        /* and free it */
  411.         h->next = freeHist;
  412.         freeHist = h;
  413.         h = p;
  414.           }
  415.         else
  416.         break;
  417.       }
  418.       }
  419.  
  420.     p->next = last_hist;
  421.     p = h;
  422.     /* p now points to the 1st event in the future (to be deleted) */
  423.     if( p != last_hist )
  424.       {
  425.     while( h->next != last_hist )
  426.         h = h->next;
  427.     h->next = freeHist;
  428.     freeHist = p;
  429.       }
  430.  
  431.     h = nd->curr;
  432.     nd->npot = h->val;
  433.     nd->c.time = h->time;
  434.     if( h->inp )
  435.     nd->nflags |= INPUT;
  436.  
  437.     if( nd->ngate != NULL )        /* recompute transistor states */
  438.       {
  439.     register lptr  l;
  440.     register tptr  t;
  441.  
  442.     for( l = nd->ngate; l != NULL; l = l->next )
  443.       {
  444.         t = l->xtor;
  445.         t->state = compute_trans_state( t );
  446.       }
  447.       }
  448.     return( 0 );
  449.   }
  450.